package com.thoughtworks.impersonator.http.record;

import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.junit.Before;
import org.junit.Test;

import com.thoughtworks.impersonator.http.message.HttpExchange;
import com.thoughtworks.impersonator.http.message.storage.HttpExchangeStorage;


public class ServerConnectionHandlerTest {

    private ServerConnectionHandler handler;
    private ChannelHandlerContext clientContext;
    private Channel clientConnection;
    private HttpExchangeStorage exchangeStorage;
    
    @Before
    public void createHandler() {
        clientContext = mock(ChannelHandlerContext.class);
        clientConnection = mock(Channel.class);
        exchangeStorage = mock(HttpExchangeStorage.class);
        handler = new ServerConnectionHandler(clientContext, clientConnection, exchangeStorage);
    }

    @Test
    public void shouldProxyResponseBackToClient() throws Exception {
        ChannelHandlerContext serverContext = mock(ChannelHandlerContext.class);
        MessageEvent event = mock(MessageEvent.class);
        HttpResponse response = mock(HttpResponse.class);
        
        when(event.getMessage()).thenReturn(response);
        
        handler.messageReceived(serverContext, event);
        
        verify(clientConnection).write(response);
    }
    
    @Test
    public void shouldForwardCompleteHttpExchangeToClientContext() throws Exception {
        ChannelHandlerContext serverContext = mock(ChannelHandlerContext.class);
        MessageEvent event = mock(MessageEvent.class);
        HttpResponse response = mock(HttpResponse.class);
        HttpRequest request = mock(HttpRequest.class);
        
        when(clientContext.getAttachment()).thenReturn(request);
        when(event.getMessage()).thenReturn(response);
        
        handler.messageReceived(serverContext, event);
        
        verify(clientContext).setAttachment(new HttpExchange(request, response));
    }
    
    @Test
    public void shouldCloseConnectionAfterReceivingResponse() throws Exception {
        ChannelHandlerContext serverContext = mock(ChannelHandlerContext.class);
        MessageEvent event = mock(MessageEvent.class);
        Channel channel = mock(Channel.class);
        ChannelFuture future = mock(ChannelFuture.class);
        
        when(event.getChannel()).thenReturn(channel);
        when(channel.isOpen()).thenReturn(true);
        when(channel.isConnected()).thenReturn(true);        
        when(channel.write(anyObject())).thenReturn(future);
        
        handler.messageReceived(serverContext, event);
        
        verify(future).addListener(ChannelFutureListener.CLOSE);
    }
}
